package ua.org.extjsbuilder.wizards;

import java.lang.reflect.InvocationTargetException;
import java.net.URI;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;

import ua.org.extjsbuilder.projects.ExtjsProjectConfiguration;
import ua.org.extjsbuilder.projects.ExtjsProjectNature;

public class ExtjsNewProjectWizard extends Wizard implements INewWizard {
	private ExtjsNewProjectWizardPage page;

	public ExtjsNewProjectWizard() {
		super();
		setNeedsProgressMonitor(true);
	}
	
	public void init(IWorkbench workbench, IStructuredSelection selection) {}
	
	public void addPages() {
		page = new ExtjsNewProjectWizardPage();
		addPage(page);
	}

	public boolean performFinish() {
		final String name = page.getProjectName();
		IRunnableWithProgress op = new IRunnableWithProgress() {
			public void run(IProgressMonitor monitor) throws InvocationTargetException {
				try {
					doFinish(name, monitor);
				} catch (CoreException e) {
					throw new InvocationTargetException(e);
				} finally {
					monitor.done();
				}
			}
		};
		try {
			getContainer().run(true, false, op);
		} catch (InterruptedException e) {
			return false;
		} catch (InvocationTargetException e) {
			Throwable realException = e.getTargetException();
			MessageDialog.openError(getShell(), "Error", realException.getMessage());
			return false;
		}
		return true;
	}
	
	private void doFinish(String name,IProgressMonitor monitor)
			throws CoreException {
		monitor.beginTask("Creating Extjs Project " + name, 2);
		ResourcesPlugin.getWorkspace().newProjectDescription(name);
		monitor.worked(1);
		IProject newProject = createBaseProject(name,null);//TODO: allow custom location
		addExtjsProjectNature(newProject, newProject.getDescription());
		monitor.worked(1);
		
		createDirs(newProject,ExtjsProjectConfiguration.getInstance(newProject));
		
		monitor.worked(1);
	}

	private void createDirs(IProject newProject,ExtjsProjectConfiguration config) 
			throws CoreException {
		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
		IResource resource = root.findMember(new Path(newProject.getName()));
		IContainer container = (IContainer) resource;
		
		createDir(container,config.getBinaryDir(),IResource.TEAM_PRIVATE|IResource.FORCE);
		createDir(container,config.getSourceDir(),IResource.FORCE);
	}

	private void createDir(IContainer container, IPath dir,int flags) 
			throws CoreException {
		final IFolder folder = container.getFolder(dir);
		if(!folder.exists()){
			folder.create(flags, true, null);
		}
	}

	private void addExtjsProjectNature(IProject newProject,
			IProjectDescription description) {
		try {
			
			String[] natures = description.getNatureIds();

			// Add the nature
			String[] newNatures = new String[natures.length + 1];
			System.arraycopy(natures, 0, newNatures, 0, natures.length);
			newNatures[natures.length] = ExtjsProjectNature.NATURE_ID;
			description.setNatureIds(newNatures);
			newProject.setDescription(description, null);
		} catch (CoreException e) {
			throw new RuntimeException(e);
		}
		
	}
	
	private IProject createBaseProject(String projectName, URI location) {
		IProject newProject = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
		
		if (!newProject.exists()) {
			URI projectLocation = location;
			IProjectDescription desc = newProject.getWorkspace().newProjectDescription(newProject.getName());
			if (location != null && ResourcesPlugin.getWorkspace()
					.getRoot().getLocationURI().equals(location)) {
				projectLocation = null;
			}

			desc.setLocationURI(projectLocation);
			
			try {
				newProject.create(desc, null);
				if (!newProject.isOpen()) {
					newProject.open(null);
				}
				return newProject;
			} catch (CoreException e) {
				throw new RuntimeException(e);
			}
		}
		throw new RuntimeException("Project is already exists");
	}
}